{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurations for Colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "IN_COLAB = 'google.colab' in sys.modules\n",
    "\n",
    "if IN_COLAB:\n",
    "    !apt-get install -y xvfb python-opengl > /dev/null 2>&1\n",
    "    !pip install gym pyvirtualdisplay > /dev/null 2>&1\n",
    "    !pip install JSAnimation==0.1\n",
    "    \n",
    "    from pyvirtualdisplay import Display\n",
    "    \n",
    "    # Start virtual display\n",
    "    dis = Display(visible=0, size=(400, 400))\n",
    "    dis.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 02. Double DQN\n",
    "\n",
    "[van Hasselt et al., \"Deep Reinforcement Learning with Double Q-learning.\" arXiv preprint arXiv:1509.06461, 2015.](https://arxiv.org/pdf/1509.06461.pdf)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "Let's take a close look at the difference between DQN and Double-DQN. The max operator in standard Q-learning and DQN uses the same values both to select and to evaluate an action. This makes it more likely to select overestimated values, resulting in overoptimistic value estimates.\n",
    "\n",
    "$$\n",
    "\\theta_{t+1} = \\theta_t + \\alpha \\big(Y_t^Q - Q(S_t, A_t; \\theta_t)\\big) \\cdot \\nabla_{\\theta_t} Q(S_t, A_t; \\theta_t),\\\\\n",
    "\\text{where } \\alpha \\text{ is a scalar step size and the target } Y_t^Q \\text{is defined as }\\\\\n",
    "Y_t^Q = R_{t+1} + \\gamma \\max_a Q(S_{t+1}, a; \\theta_t).\n",
    "$$\n",
    "\n",
    "In Double Q-learning ([van Hasselt 2010](https://papers.nips.cc/paper/3964-double-q-learning.pdf)), two value functions are learned by assigning experiences randomly to update one of the two value functions, resulting in two sets of weights, $\\theta$ and $\\theta'$. For each update, one set of weights is used to determine the greedy policy and the other to determine its value. For a clear comparison, we can untangle the selection and evaluation in Q-learning and rewrite DQN's target as\n",
    "\n",
    "$$\n",
    "Y_t^Q = R_{t+1} + \\gamma \\max_a Q(S_{t+1}, \\arg\\max_a Q(S_{t+1}, a; \\theta_t); \\theta_t).\n",
    "$$\n",
    "\n",
    "The Double Q-learning error can then be written as\n",
    "\n",
    "$$\n",
    "Y_t^{DoubleQ} = R_{t+1} + \\gamma \\max_a Q(S_{t+1}, \\arg\\max_a Q(S_{t+1}, a; \\theta_t); \\theta_t').\n",
    "$$\n",
    "\n",
    "The idea of Double Q-learning is to reduce overestimations by decomposing the max operation in the target into action selection and action evaluation. Although not fully decoupled, the target network in the DQN architecture provides a natural candidate for the second value function, without having to introduce additional networks. In conclusion, the weights of the second network $\\theta_t'$ are replaced with the weights of the target network for the evaluation of the current greedy policy. This makes just a small change in calculating the target value of DQN loss.\n",
    "\n",
    "##### DQN:\n",
    "\n",
    "```\n",
    "target = reward + gamma * dqn_target(next_state).max(dim=1, keepdim=True)[0]\n",
    "```\n",
    "\n",
    "##### DoubleDQN:\n",
    "\n",
    "```\n",
    "selected_action = dqn(next_state).argmax(dim=1, keepdim=True)\n",
    "target = reward + gamma * dqn_target(next_state).gather(1, selected_action)\n",
    "```\n",
    "      "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from typing import Dict, List, Tuple\n",
    "\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from IPython.display import clear_output\n",
    "from torch.nn.utils import clip_grad_norm_"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replay buffer\n",
    "\n",
    "Please see *01.dqn.ipynb* for detailed description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    \"\"\"A simple numpy replay buffer.\"\"\"\n",
    "\n",
    "    def __init__(self, obs_dim: int, size: int, batch_size: int = 32):\n",
    "        self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.acts_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.rews_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.done_buf = np.zeros(size, dtype=np.float32)\n",
    "        self.max_size, self.batch_size = size, batch_size\n",
    "        self.ptr, self.size, = 0, 0\n",
    "\n",
    "    def store(\n",
    "        self,\n",
    "        obs: np.ndarray,\n",
    "        act: np.ndarray, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool,\n",
    "    ):\n",
    "        self.obs_buf[self.ptr] = obs\n",
    "        self.next_obs_buf[self.ptr] = next_obs\n",
    "        self.acts_buf[self.ptr] = act\n",
    "        self.rews_buf[self.ptr] = rew\n",
    "        self.done_buf[self.ptr] = done\n",
    "        self.ptr = (self.ptr + 1) % self.max_size\n",
    "        self.size = min(self.size + 1, self.max_size)\n",
    "\n",
    "    def sample_batch(self) -> Dict[str, np.ndarray]:\n",
    "        idxs = np.random.choice(self.size, size=self.batch_size, replace=False)\n",
    "        return dict(obs=self.obs_buf[idxs],\n",
    "                    next_obs=self.next_obs_buf[idxs],\n",
    "                    acts=self.acts_buf[idxs],\n",
    "                    rews=self.rews_buf[idxs],\n",
    "                    done=self.done_buf[idxs])\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Network\n",
    "\n",
    "We are going to use a simple network architecture with three fully connected layers and two non-linearity functions (ReLU)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Network(nn.Module):\n",
    "    def __init__(self, in_dim: int, out_dim: int):\n",
    "        \"\"\"Initialization.\"\"\"\n",
    "        super(Network, self).__init__()\n",
    "\n",
    "        self.layers = nn.Sequential(\n",
    "            nn.Linear(in_dim, 128), \n",
    "            nn.ReLU(),\n",
    "            nn.Linear(128, 128), \n",
    "            nn.ReLU(), \n",
    "            nn.Linear(128, out_dim)\n",
    "        )\n",
    "\n",
    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        return self.layers(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Double DQN Agent\n",
    "\n",
    "Here is a summary of DQNAgent class.\n",
    "\n",
    "| Method           | Note                                                 |\n",
    "| ---              | ---                                                  |\n",
    "|select_action     | select an action from the input state.               |\n",
    "|step              | take an action and return the response of the env.   |\n",
    "|compute_dqn_loss  | return dqn loss.                                     |\n",
    "|update_model      | update the model by gradient descent.                |\n",
    "|target_hard_update| hard update from the local model to the target model.|\n",
    "|train             | train the agent during num_frames.                   |\n",
    "|test              | test the agent (1 episode).                          |\n",
    "|plot              | plot the training progresses.                        |\n",
    "\n",
    "We use `self.dqn` instead of `self.dqn_target` for action selection.\n",
    "\n",
    "```\n",
    "\n",
    "        next_q_value = self.dqn_target(next_state).gather(\n",
    "            1, self.dqn(next_state).argmax(dim=1, keepdim=True)  # Double DQN\n",
    "        ).detach()\n",
    "        mask = 1 - done\n",
    "        target = (reward + self.gamma * next_q_value * mask).to(self.device)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNAgent:\n",
    "    \"\"\"DQN Agent interacting with environment.\n",
    "    \n",
    "    Attribute:\n",
    "        env (gym.Env): openAI Gym environment\n",
    "        memory (ReplayBuffer): replay memory to store transitions\n",
    "        batch_size (int): batch size for sampling\n",
    "        epsilon (float): parameter for epsilon greedy policy\n",
    "        epsilon_decay (float): step size to decrease epsilon\n",
    "        max_epsilon (float): max value of epsilon\n",
    "        min_epsilon (float): min value of epsilon\n",
    "        target_update (int): period for target model's hard update\n",
    "        gamma (float): discount factor\n",
    "        dqn (Network): model to train and select actions\n",
    "        dqn_target (Network): target model to update\n",
    "        optimizer (torch.optim): optimizer for training dqn\n",
    "        transition (list): transition information including \n",
    "                           state, action, reward, next_state, done\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        env: gym.Env,\n",
    "        memory_size: int,\n",
    "        batch_size: int,\n",
    "        target_update: int,\n",
    "        epsilon_decay: float,\n",
    "        max_epsilon: float = 1.0,\n",
    "        min_epsilon: float = 0.1,\n",
    "        gamma: float = 0.99,\n",
    "    ):\n",
    "        \"\"\"Initialization.\n",
    "        \n",
    "        Args:\n",
    "            env (gym.Env): openAI Gym environment\n",
    "            memory_size (int): length of memory\n",
    "            batch_size (int): batch size for sampling\n",
    "            target_update (int): period for target model's hard update\n",
    "            epsilon_decay (float): step size to decrease epsilon\n",
    "            lr (float): learning rate\n",
    "            max_epsilon (float): max value of epsilon\n",
    "            min_epsilon (float): min value of epsilon\n",
    "            gamma (float): discount factor\n",
    "        \"\"\"\n",
    "        obs_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.n\n",
    "        \n",
    "        self.env = env\n",
    "        self.memory = ReplayBuffer(obs_dim, memory_size, batch_size)\n",
    "        self.batch_size = batch_size\n",
    "        self.epsilon = max_epsilon\n",
    "        self.epsilon_decay = epsilon_decay\n",
    "        self.max_epsilon = max_epsilon\n",
    "        self.min_epsilon = min_epsilon\n",
    "        self.target_update = target_update\n",
    "        self.gamma = gamma\n",
    "        \n",
    "        # device: cpu / gpu\n",
    "        self.device = torch.device(\n",
    "            \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "        )\n",
    "        print(self.device)\n",
    "\n",
    "        # networks: dqn, dqn_target\n",
    "        self.dqn = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "        self.dqn_target.eval()\n",
    "        \n",
    "        # optimizer\n",
    "        self.optimizer = optim.Adam(self.dqn.parameters())\n",
    "\n",
    "        # transition to store in memory\n",
    "        self.transition = list()\n",
    "        \n",
    "        # mode: train / test\n",
    "        self.is_test = False\n",
    "\n",
    "    def select_action(self, state: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Select an action from the input state.\"\"\"\n",
    "        # epsilon greedy policy\n",
    "        if self.epsilon > np.random.random():\n",
    "            selected_action = self.env.action_space.sample()\n",
    "        else:\n",
    "            selected_action = self.dqn(\n",
    "                torch.FloatTensor(state).to(self.device)\n",
    "            ).argmax()\n",
    "            selected_action = selected_action.detach().cpu().numpy()\n",
    "        \n",
    "        if not self.is_test:\n",
    "            self.transition = [state, selected_action]\n",
    "        \n",
    "        return selected_action\n",
    "\n",
    "    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n",
    "        \"\"\"Take an action and return the response of the env.\"\"\"\n",
    "        next_state, reward, done, _ = self.env.step(action)\n",
    "\n",
    "        if not self.is_test:\n",
    "            self.transition += [reward, next_state, done]\n",
    "            self.memory.store(*self.transition)\n",
    "    \n",
    "        return next_state, reward, done\n",
    "\n",
    "    def update_model(self) -> torch.Tensor:\n",
    "        \"\"\"Update the model by gradient descent.\"\"\"\n",
    "        samples = self.memory.sample_batch()\n",
    "\n",
    "        loss = self._compute_dqn_loss(samples)\n",
    "\n",
    "        self.optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        # gradient clipping\n",
    "        # https://pytorch.org/docs/stable/nn.html#torch.nn.utils.clip_grad_norm_\n",
    "        clip_grad_norm_(self.dqn.parameters(), 1.0, norm_type=1)\n",
    "        self.optimizer.step()\n",
    "\n",
    "        return loss.item()\n",
    "        \n",
    "    def train(self, num_frames: int, plotting_interval: int = 200):\n",
    "        \"\"\"Train the agent.\"\"\"\n",
    "        self.is_test = False\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        update_cnt = 0\n",
    "        epsilons = []\n",
    "        losses = []\n",
    "        scores = []\n",
    "        score = 0\n",
    "\n",
    "        for frame_idx in range(1, num_frames + 1):\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "\n",
    "            # if episode ends\n",
    "            if done:\n",
    "                state = env.reset()\n",
    "                scores.append(score)\n",
    "                score = 0\n",
    "\n",
    "            # if training is ready\n",
    "            if len(self.memory) >= self.batch_size:\n",
    "                loss = self.update_model()\n",
    "                losses.append(loss)\n",
    "                update_cnt += 1\n",
    "                \n",
    "                # linearly decrease epsilon\n",
    "                self.epsilon = max(\n",
    "                    self.min_epsilon, self.epsilon - (\n",
    "                        self.max_epsilon - self.min_epsilon\n",
    "                    ) * self.epsilon_decay\n",
    "                )\n",
    "                epsilons.append(self.epsilon)\n",
    "                \n",
    "                # if hard update is needed\n",
    "                if update_cnt % self.target_update == 0:\n",
    "                    self._target_hard_update()\n",
    "\n",
    "            # plotting\n",
    "            if frame_idx % plotting_interval == 0:\n",
    "                self._plot(frame_idx, scores, losses, epsilons)\n",
    "                \n",
    "        self.env.close()\n",
    "                \n",
    "    def test(self) -> List[np.ndarray]:\n",
    "        \"\"\"Test the agent.\"\"\"\n",
    "        self.is_test = True\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        done = False\n",
    "        score = 0\n",
    "        \n",
    "        frames = []\n",
    "        while not done:\n",
    "            frames.append(self.env.render(mode=\"rgb_array\"))\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "        \n",
    "        print(\"score: \", score)\n",
    "        self.env.close()\n",
    "        \n",
    "        return frames\n",
    "\n",
    "    def _compute_dqn_loss(self, samples: Dict[str, np.ndarray]) -> torch.Tensor:\n",
    "        \"\"\"Return dqn loss.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n",
    "        action = torch.LongTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "        reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n",
    "        done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n",
    "        \n",
    "        # G_t   = r + gamma * v(s_{t+1})  if state != Terminal\n",
    "        #       = r                       otherwise\n",
    "        curr_q_value = self.dqn(state).gather(1, action)\n",
    "        next_q_value = self.dqn_target(next_state).gather(  # Double DQN\n",
    "            1, self.dqn(next_state).argmax(dim=1, keepdim=True)\n",
    "        ).detach()\n",
    "        mask = 1 - done\n",
    "        target = (reward + self.gamma * next_q_value * mask).to(self.device)\n",
    "\n",
    "        # calculate dqn loss\n",
    "        loss = ((target - curr_q_value).pow(2)).mean()\n",
    "\n",
    "        return loss\n",
    "    \n",
    "    def _target_hard_update(self):\n",
    "        \"\"\"Hard update: target <- local.\"\"\"\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "                \n",
    "    def _plot(\n",
    "        self, \n",
    "        frame_idx: int, \n",
    "        scores: List[float], \n",
    "        losses: List[float], \n",
    "        epsilons: List[float],\n",
    "    ):\n",
    "        \"\"\"Plot the training progresses.\"\"\"\n",
    "        clear_output(True)\n",
    "        plt.figure(figsize=(20, 5))\n",
    "        plt.subplot(131)\n",
    "        plt.title('frame %s. score: %s' % (frame_idx, np.mean(scores[-10:])))\n",
    "        plt.plot(scores)\n",
    "        plt.subplot(132)\n",
    "        plt.title('loss')\n",
    "        plt.plot(losses)\n",
    "        plt.subplot(133)\n",
    "        plt.title('epsilons')\n",
    "        plt.plot(epsilons)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment\n",
    "\n",
    "You can see the [code](https://github.com/openai/gym/blob/master/gym/envs/classic_control/cartpole.py) and [configurations](https://github.com/openai/gym/blob/master/gym/envs/__init__.py#L53) of CartPole-v0 from OpenAI's repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "env_id = \"CartPole-v0\"\n",
    "env = gym.make(env_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set random seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[777]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seed = 777\n",
    "\n",
    "def seed_torch(seed):\n",
    "    torch.manual_seed(seed)\n",
    "    if torch.backends.cudnn.enabled:\n",
    "        torch.backends.cudnn.benchmark = False\n",
    "        torch.backends.cudnn.deterministic = True\n",
    "\n",
    "np.random.seed(seed)\n",
    "seed_torch(seed)\n",
    "env.seed(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n"
     ]
    }
   ],
   "source": [
    "# parameters\n",
    "num_frames = 10000\n",
    "memory_size = 1000\n",
    "batch_size = 32\n",
    "target_update = 200\n",
    "epsilon_decay = 1 / 2000\n",
    "\n",
    "# train\n",
    "agent = DQNAgent(env, memory_size, batch_size, target_update, epsilon_decay)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "agent.train(num_frames)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test\n",
    "\n",
    "Run the trained agent (1 episode)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score:  200.0\n"
     ]
    }
   ],
   "source": [
    "frames = agent.test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Define the Animation class */\n",
       "  function Animation(frames, img_id, slider_id, interval, loop_select_id){\n",
       "    this.img_id = img_id;\n",
       "    this.slider_id = slider_id;\n",
       "    this.loop_select_id = loop_select_id;\n",
       "    this.interval = interval;\n",
       "    this.current_frame = 0;\n",
       "    this.direction = 0;\n",
       "    this.timer = null;\n",
       "    this.frames = new Array(frames.length);\n",
       "\n",
       "    for (var i=0; i<frames.length; i++)\n",
       "    {\n",
       "     this.frames[i] = new Image();\n",
       "     this.frames[i].src = frames[i];\n",
       "    }\n",
       "    document.getElementById(this.slider_id).max = this.frames.length - 1;\n",
       "    this.set_frame(this.current_frame);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.get_loop_state = function(){\n",
       "    var button_group = document[this.loop_select_id].state;\n",
       "    for (var i = 0; i < button_group.length; i++) {\n",
       "        var button = button_group[i];\n",
       "        if (button.checked) {\n",
       "            return button.value;\n",
       "        }\n",
       "    }\n",
       "    return undefined;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.set_frame = function(frame){\n",
       "    this.current_frame = frame;\n",
       "    document.getElementById(this.img_id).src = this.frames[this.current_frame].src;\n",
       "    document.getElementById(this.slider_id).value = this.current_frame;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.next_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.previous_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.max(0, this.current_frame - 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.first_frame = function()\n",
       "  {\n",
       "    this.set_frame(0);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.last_frame = function()\n",
       "  {\n",
       "    this.set_frame(this.frames.length - 1);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.slower = function()\n",
       "  {\n",
       "    this.interval /= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.faster = function()\n",
       "  {\n",
       "    this.interval *= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_forward = function()\n",
       "  {\n",
       "    this.current_frame += 1;\n",
       "    if(this.current_frame < this.frames.length){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.first_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.last_frame();\n",
       "        this.reverse_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.last_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_reverse = function()\n",
       "  {\n",
       "    this.current_frame -= 1;\n",
       "    if(this.current_frame >= 0){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.last_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.first_frame();\n",
       "        this.play_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.first_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.pause_animation = function()\n",
       "  {\n",
       "    this.direction = 0;\n",
       "    if (this.timer){\n",
       "      clearInterval(this.timer);\n",
       "      this.timer = null;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.play_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = 1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_forward();}, this.interval);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.reverse_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = -1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_reverse();}, this.interval);\n",
       "  }\n",
       "</script>\n",
       "\n",
       "<div class=\"animation\" align=\"center\">\n",
       "    <img id=\"_anim_imgSOSJXMDWCWSVXYME\">\n",
       "    <br>\n",
       "    <input id=\"_anim_sliderSOSJXMDWCWSVXYME\" type=\"range\" style=\"width:350px\" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\" onchange=\"animSOSJXMDWCWSVXYME.set_frame(parseInt(this.value));\"></input>\n",
       "    <br>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.slower()\">&#8211;</button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.first_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.previous_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.reverse_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.pause_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.play_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.next_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.last_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animSOSJXMDWCWSVXYME.faster()\">+</button>\n",
       "  <form action=\"#n\" name=\"_anim_loop_selectSOSJXMDWCWSVXYME\" class=\"anim_control\">\n",
       "    <input type=\"radio\" name=\"state\" value=\"once\" > Once </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"loop\" checked> Loop </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"reflect\" > Reflect </input>\n",
       "  </form>\n",
       "</div>\n",
       "\n",
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Instantiate the Animation class. */\n",
       "  /* The IDs given should match those used in the template above. */\n",
       "  (function() {\n",
       "    var img_id = \"_anim_imgSOSJXMDWCWSVXYME\";\n",
       "    var slider_id = \"_anim_sliderSOSJXMDWCWSVXYME\";\n",
       "    var loop_select_id = \"_anim_loop_selectSOSJXMDWCWSVXYME\";\n",
       "    var frames = new Array(0);\n",
       "    \n",
       "  frames[0] = \"\"\n",
       "  frames[1] = \"\"\n",
       "  frames[2] = \"\"\n",
       "  frames[3] = \"\"\n",
       "  frames[4] = \"\"\n",
       "  frames[5] = \"\"\n",
       "  frames[6] = \"\"\n",
       "  frames[7] = \"\"\n",
       "  frames[8] = \"\"\n",
       "  frames[9] = \"\"\n",
       "  frames[10] = \"\"\n",
       "  frames[11] = \"\"\n",
       "  frames[12] = \"\"\n",
       "  frames[13] = \"\"\n",
       "  frames[14] = \"\"\n",
       "  frames[15] = \"\"\n",
       "  frames[16] = \"\"\n",
       "  frames[17] = \"\"\n",
       "  frames[18] = \"\"\n",
       "  frames[19] = \"\"\n",
       "  frames[20] = \"\"\n",
       "  frames[21] = \"\"\n",
       "  frames[22] = \"\"\n",
       "  frames[23] = \"\"\n",
       "  frames[24] = \"\"\n",
       "  frames[25] = \"\"\n",
       "  frames[26] = \"\"\n",
       "  frames[27] = \"\"\n",
       "  frames[28] = \"\"\n",
       "  frames[29] = \"\"\n",
       "  frames[30] = \"\"\n",
       "  frames[31] = \"\"\n",
       "  frames[32] = \"\"\n",
       "  frames[33] = \"\"\n",
       "  frames[34] = \"\"\n",
       "  frames[35] = \"\"\n",
       "  frames[36] = \"\"\n",
       "  frames[37] = \"\"\n",
       "  frames[38] = \"\"\n",
       "  frames[39] = \"\"\n",
       "  frames[40] = \"\"\n",
       "  frames[41] = \"\"\n",
       "  frames[42] = \"\"\n",
       "  frames[43] = \"\"\n",
       "  frames[44] = \"\"\n",
       "  frames[45] = \"\"\n",
       "  frames[46] = \"\"\n",
       "  frames[47] = \"\"\n",
       "  frames[48] = \"\"\n",
       "  frames[49] = \"\"\n",
       "  frames[50] = \"\"\n",
       "  frames[51] = \"\"\n",
       "  frames[52] = \"\"\n",
       "  frames[53] = \"\"\n",
       "  frames[54] = \"\"\n",
       "  frames[55] = \"\"\n",
       "  frames[56] = \"\"\n",
       "  frames[57] = \"\"\n",
       "  frames[58] = \"\"\n",
       "  frames[59] = \"\"\n",
       "  frames[60] = \"\"\n",
       "  frames[61] = \"\"\n",
       "  frames[62] = \"\"\n",
       "  frames[63] = \"\"\n",
       "  frames[64] = \"\"\n",
       "  frames[65] = \"\"\n",
       "  frames[66] = \"\"\n",
       "  frames[67] = \"\"\n",
       "  frames[68] = \"\"\n",
       "  frames[69] = \"\"\n",
       "  frames[70] = \"\"\n",
       "  frames[71] = \"\"\n",
       "  frames[72] = \"\"\n",
       "  frames[73] = \"\"\n",
       "  frames[74] = \"\"\n",
       "  frames[75] = \"\"\n",
       "  frames[76] = \"\"\n",
       "  frames[77] = \"\"\n",
       "  frames[78] = \"\"\n",
       "  frames[79] = \"\"\n",
       "  frames[80] = \"\"\n",
       "  frames[81] = \"\"\n",
       "  frames[82] = \"\"\n",
       "  frames[83] = \"\"\n",
       "  frames[84] = \"\"\n",
       "  frames[85] = \"\"\n",
       "  frames[86] = \"\"\n",
       "  frames[87] = \"\"\n",
       "  frames[88] = \"\"\n",
       "  frames[89] = \"\"\n",
       "  frames[90] = \"\"\n",
       "  frames[91] = \"\"\n",
       "  frames[92] = \"\"\n",
       "  frames[93] = \"\"\n",
       "  frames[94] = \"\"\n",
       "  frames[95] = \"\"\n",
       "  frames[96] = \"\"\n",
       "  frames[97] = \"\"\n",
       "  frames[98] = \"\"\n",
       "  frames[99] = \"\"\n",
       "  frames[100] = \"\"\n",
       "  frames[101] = \"\"\n",
       "  frames[102] = \"\"\n",
       "  frames[103] = \"\"\n",
       "  frames[104] = \"\"\n",
       "  frames[105] = \"\"\n",
       "  frames[106] = \"\"\n",
       "  frames[107] = \"\"\n",
       "  frames[108] = \"\"\n",
       "  frames[109] = \"\"\n",
       "  frames[110] = \"\"\n",
       "  frames[111] = \"\"\n",
       "  frames[112] = \"\"\n",
       "  frames[113] = \"\"\n",
       "  frames[114] = \"\"\n",
       "  frames[115] = \"\"\n",
       "  frames[116] = \"\"\n",
       "  frames[117] = \"\"\n",
       "  frames[118] = \"\"\n",
       "  frames[119] = \"\"\n",
       "  frames[120] = \"\"\n",
       "  frames[121] = \"\"\n",
       "  frames[122] = \"\"\n",
       "  frames[123] = \"\"\n",
       "  frames[124] = \"\"\n",
       "  frames[125] = \"\"\n",
       "  frames[126] = \"\"\n",
       "  frames[127] = \"\"\n",
       "  frames[128] = \"\"\n",
       "  frames[129] = \"\"\n",
       "  frames[130] = \"\"\n",
       "  frames[131] = \"\"\n",
       "  frames[132] = \"\"\n",
       "  frames[133] = \"\"\n",
       "  frames[134] = \"\"\n",
       "  frames[135] = \"\"\n",
       "  frames[136] = \"\"\n",
       "  frames[137] = \"\"\n",
       "  frames[138] = \"\"\n",
       "  frames[139] = \"\"\n",
       "  frames[140] = \"\"\n",
       "  frames[141] = \"\"\n",
       "  frames[142] = \"\"\n",
       "  frames[143] = \"\"\n",
       "  frames[144] = \"\"\n",
       "  frames[145] = \"\"\n",
       "  frames[146] = \"\"\n",
       "  frames[147] = \"\"\n",
       "  frames[148] = \"\"\n",
       "  frames[149] = \"\"\n",
       "  frames[150] = \"\"\n",
       "  frames[151] = \"\"\n",
       "  frames[152] = \"\"\n",
       "  frames[153] = \"\"\n",
       "  frames[154] = \"\"\n",
       "  frames[155] = \"\"\n",
       "  frames[156] = \"\"\n",
       "  frames[157] = \"\"\n",
       "  frames[158] = \"\"\n",
       "  frames[159] = \"\"\n",
       "  frames[160] = \"\"\n",
       "  frames[161] = \"\"\n",
       "  frames[162] = \"\"\n",
       "  frames[163] = \"\"\n",
       "  frames[164] = \"\"\n",
       "  frames[165] = \"\"\n",
       "  frames[166] = \"\"\n",
       "  frames[167] = \"\"\n",
       "  frames[168] = \"\"\n",
       "  frames[169] = \"\"\n",
       "  frames[170] = \"\"\n",
       "  frames[171] = \"\"\n",
       "  frames[172] = \"\"\n",
       "  frames[173] = \"\"\n",
       "  frames[174] = \"\"\n",
       "  frames[175] = \"\"\n",
       "  frames[176] = \"\"\n",
       "  frames[177] = \"\"\n",
       "  frames[178] = \"\"\n",
       "  frames[179] = \"\"\n",
       "  frames[180] = \"\"\n",
       "  frames[181] = \"\"\n",
       "  frames[182] = \"\"\n",
       "  frames[183] = \"\"\n",
       "  frames[184] = \"\"\n",
       "  frames[185] = \"\"\n",
       "  frames[186] = \"\"\n",
       "  frames[187] = \"\"\n",
       "  frames[188] = \"\"\n",
       "  frames[189] = \"\"\n",
       "  frames[190] = \"\"\n",
       "  frames[191] = \"\"\n",
       "  frames[192] = \"\"\n",
       "  frames[193] = \"\"\n",
       "  frames[194] = \"\"\n",
       "  frames[195] = \"\"\n",
       "  frames[196] = \"\"\n",
       "  frames[197] = \"\"\n",
       "  frames[198] = \"\"\n",
       "  frames[199] = \"\"\n",
       "\n",
       "\n",
       "    /* set a timeout to make sure all the above elements are created before\n",
       "       the object is initialized. */\n",
       "    setTimeout(function() {\n",
       "        animSOSJXMDWCWSVXYME = new Animation(frames, img_id, slider_id, 50, loop_select_id);\n",
       "    }, 0);\n",
       "  })()\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Imports specifically so we can render outputs in Colab.\n",
    "from matplotlib import animation\n",
    "from JSAnimation.IPython_display import display_animation\n",
    "from IPython.display import display\n",
    "\n",
    "\n",
    "def display_frames_as_gif(frames):\n",
    "    \"\"\"Displays a list of frames as a gif, with controls.\"\"\"\n",
    "    patch = plt.imshow(frames[0])\n",
    "    plt.axis('off')\n",
    "\n",
    "    def animate(i):\n",
    "        patch.set_data(frames[i])\n",
    "\n",
    "    anim = animation.FuncAnimation(\n",
    "        plt.gcf(), animate, frames = len(frames), interval=50\n",
    "    )\n",
    "    display(display_animation(anim, default_mode='loop'))\n",
    "    \n",
    "        \n",
    "# display \n",
    "display_frames_as_gif(frames)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
